<template>
  <div id="pictureManagePage">
    <a-flex justify="space-between">
      <h2 style="margin-left: 100px">图片管理</h2>
      <a-space style="margin-right: 100px">
        <!-- 主色调搜索 -->
        <a-form-item label="主色调相似匹配" style="margin-top: 23px">
          <color-picker format="hex" @pureColorChange="onColorChange" />
        </a-form-item>
        <a-button type="primary" href="/add_picture" :icon="h(FileAddOutlined)">创建图片</a-button>
        <a-button type="primary" href="/add_picture/batch" :icon="h(FolderAddOutlined)">
          批量创建
        </a-button>
      </a-space>
    </a-flex>
    <!-- 图片搜索表单 -->
    <div style="display: flex; margin: auto; align-items: center; justify-content: center">
      <a-form layout="inline" :model="searchParams">
        <a-form-item>
          <a-input
            v-model:value="searchParams.id"
            placeholder="精确搜索"
            allow-clear
            @change="doSearch"
          />
        </a-form-item>
        <a-form-item>
          <a-input
            v-model:value="searchParams.searchText"
            placeholder="模糊搜索图片名、简介、分类、标签"
            style="min-width: 265px"
            allow-clear
            @change="doSearch"
          />
        </a-form-item>
        <a-form-item>
          <a-auto-complete
            v-model:value="searchParams.category"
            placeholder="输入搜索分类"
            :options="categoryOptions"
            style="min-width: 180px"
            allow-clear
            @change="doSearch"
          />
        </a-form-item>
        <a-form-item>
          <a-select
            v-model:value="searchParams.tags"
            mode="tags"
            placeholder="输入搜索标签"
            :options="tagOptions"
            style="min-width: 180px"
            allow-clear
            @change="doSearch"
          />
        </a-form-item>
        <a-form-item>
          <a-select
            v-model:value="searchParams.reviewStatus"
            placeholder="选择审核状态"
            :options="PIC_REVIEW_STATUS_OPTIONS"
            allow-clear
            style="min-width: 125px"
            @change="doSearch"
          />
        </a-form-item>
        <a-form-item>
          <a-button :icon="h(ClearOutlined)" type="primary" @click="clearSearchParams">
            重置搜索或匹配
          </a-button>
        </a-form-item>
      </a-form>
    </div>
    <div style="margin-bottom: 18px" />
    <!-- 图片数据表单 -->
    <a-table
      :columns="columns"
      :data-source="dataList"
      :pagination="pagination"
      @change="doTableChange"
      :scroll="{ x: 1300, y: 447 }"
      :loading="loading"
    >
      <template #bodyCell="{ column, record }">
        <template v-if="column.dataIndex === 'url'">
          <a-image :src="record.url" style="width: 150px" />
        </template>
        <template v-if="column.dataIndex === 'tags'">
          <a-space wrap>
            <a-tag v-for="tag in JSON.parse(record.tags || '[]')" :key="tag">
              {{ tag }}
            </a-tag>
          </a-space>
        </template>
        <template v-if="column.dataIndex === 'picInfo'">
          <div>格式：{{ record.picFormat }}</div>
          <div>宽度：{{ record.picWidth }}</div>
          <div>高度：{{ record.picHeight }}</div>
          <div>宽高比：{{ record.picScale }}</div>
          <div>大小：{{ formatSize(record.picSize) }}</div>
        </template>
        <template v-if="column.dataIndex === 'reviewMessage'">
          <div>状态：{{ PIC_REVIEW_STATUS_MAP[record.reviewStatus] }}</div>
          <div v-if="record.reviewMessage">说明：{{ record.reviewMessage }}</div>
          <div v-if="record.reviewerId">审核员Id：{{ record.reviewerId }}</div>
          <div v-if="record.reviewTime">
            审核时间：{{ dayjs(record.reviewTime).format('YYYY-MM-DD HH:mm:ss') }}
          </div>
        </template>
        <template v-if="column.dataIndex === 'createTime'">
          {{ dayjs(record.createTime).format('YYYY-MM-DD HH:mm:ss') }}
        </template>
        <template v-if="column.dataIndex === 'editTime'">
          {{ dayjs(record.editTime).format('YYYY-MM-DD HH:mm:ss') }}
        </template>
        <template v-else-if="column.key === 'action'">
          <a-space wrap>
            <a-button
              v-if="record.reviewStatus !== PIC_REVIEW_STATUS_ENUM.PASS"
              :icon="h(CheckOutlined)"
              type="primary"
              @click="handleReview(record, PIC_REVIEW_STATUS_ENUM.PASS)"
              title="过审图片"
            >
              通过
            </a-button>
            <a-button
              v-if="record.reviewStatus !== PIC_REVIEW_STATUS_ENUM.REJECT"
              :icon="h(CloseOutlined)"
              type="primary"
              style="opacity: 95%"
              danger
              @click="handleReview(record, PIC_REVIEW_STATUS_ENUM.REJECT)"
              title="使图片为 “未过审”"
            >
              拒绝
            </a-button>
            <a-button
              :icon="h(EditOutlined)"
              type="primary"
              :href="`/edit_picture?id=${record.id}`"
              title="编辑图片信息"
            >
              编辑
            </a-button>
            <!-- 删除图片 气泡确认框 -->
            <a-popconfirm
              title="确定删除该图片吗？"
              ok-text="确认"
              cancel-text="取消"
              @confirm="doDelete(record.id)"
              @cancel="cancelDelete"
            >
              <a href="#">
                <a-button
                  :icon="h(DeleteOutlined)"
                  type="primary"
                  danger
                  style="opacity: 95%"
                  title="删除图片"
                >
                  删除
                </a-button>
              </a>
            </a-popconfirm>
          </a-space>
        </template>
      </template>
    </a-table>
  </div>
</template>
<script lang="ts" setup>
import { computed, onMounted, reactive, ref, h } from 'vue'
import {
  deletePictureUsingPost,
  doPictureReviewUsingPost,
  listPictureByPageUsingPost,
  listPictureTagCategoryUsingGet,
  searchPictureForAdminByColorUsingPost,
} from '@/api/pictureController.ts'
import { message } from 'ant-design-vue'
import {
  EditOutlined,
  DeleteOutlined,
  CheckOutlined,
  CloseOutlined,
  FileAddOutlined,
  FolderAddOutlined,
  ClearOutlined,
} from '@ant-design/icons-vue'
import dayjs from 'dayjs'
import { formatSize } from '../../utils'
import {
  PIC_REVIEW_STATUS_ENUM,
  PIC_REVIEW_STATUS_MAP,
  PIC_REVIEW_STATUS_OPTIONS,
} from '../../constants/picture.ts'
import { ColorPicker } from 'vue3-colorpicker'

// 图片管理表格第一行信息
const columns = [
  {
    title: '图片ID',
    dataIndex: 'id',
    width: 110,
  },
  {
    title: '图片',
    dataIndex: 'url',
    width: 180,
  },
  {
    title: '图片名',
    dataIndex: 'name',
    ellipsis: true,
    width: 140,
  },
  {
    title: '简介',
    dataIndex: 'introduction',
    ellipsis: true,
    width: 130,
  },
  {
    title: '分类',
    dataIndex: 'category',
    ellipsis: true,
    width: 100,
  },
  {
    title: '标签',
    dataIndex: 'tags',
    width: 80,
  },
  {
    title: '图片信息',
    dataIndex: 'picInfo',
    width: 130,
  },
  {
    title: '创建人ID',
    dataIndex: 'userId',
    width: 120,
  },
  {
    title: '审核信息',
    dataIndex: 'reviewMessage',
    width: 120,
  },
  {
    title: '创建时间',
    dataIndex: 'createTime',
    width: 120,
  },
  {
    title: '编辑时间',
    dataIndex: 'editTime',
    width: 120,
  },
  {
    title: '操作',
    key: 'action',
  },
]

// 定义数据类型
const dataList = ref<API.Picture[]>([])
// 分页数据总数
const total = ref(0)
// 定义搜索条件
const searchParams = reactive<API.PictureQueryRequest>({
  current: 1,
  pageSize: 15,
  sortField: '',
  sortOrder: 'descend',
})
const loading = ref(true)
// 根据搜索条件，远程获取数据
const fetchData = async () => {
  loading.value = true
  const res = await listPictureByPageUsingPost({
    // ... 是展开运算符，它主要用于将 searchParams 对象中的所有可枚举属性展开并合并到另一个对象中，
    // 从而保证 searchParams 不会受到 fetchData 函数内其他操作的污染
    ...searchParams,
    // 管理员在图片管理页面只能查看公共图片
    // 如果要强行更新私有空间的图片信息，另行他法，不允许在图片管理页面进行更新
    nullSpaceId: true,
  })
  if (res.data.code === 0 && res.data.data) {
    dataList.value = res.data.data.records ?? []
    total.value = res.data.data.total ?? 0
  } else {
    message.error('获取图片数据失败，' + res.data.message)
  }
  loading.value = false
}

// 首次进入图片管理页面，请求一次默认搜索的图片数据
onMounted(() => {
  fetchData()
})

// 定义分页器参数
const pagination = computed(() => {
  return {
    current: searchParams.current ?? 1,
    pageSize: searchParams.pageSize ?? 10,
    total: total.value,
    showSizeChange: true,
    // @ts-ignore
    showTotal: (total) => `共 ${total} 条`,
  }
})

// 改变分页展示
const doTableChange = (page: any) => {
  searchParams.current = page.current
  searchParams.pageSize = page.pageSize
  // 重新获取数据
  fetchData()
}

// 搜索图片数据
const doSearch = () => {
  // 重置页码 搜索结束回到第一页
  searchParams.current = 1
  fetchData()
}

/**
 * 删除图片
 * @param id
 */
const doDelete = async (id: String) => {
  // 前端校验一下id是否有效
  if (!id) {
    return
  }
  // @ts-ignore
  const res = await deletePictureUsingPost({ id })
  if (res.data.code === 0) {
    message.success('删除成功')
    // 刷新数据
    fetchData()
  } else {
    message.error('删除失败，' + res.data.message)
  }
}

/**
 * 取消删除图片
 * @param e
 */
const cancelDelete = (e: MouseEvent) => {
  message.success('取消删除')
}

/**
 * 审核图片
 * @param record
 * @param reviewStatus
 */
const handleReview = async (record: API.Picture, reviewStatus: number) => {
  const reviewMessage =
    reviewStatus === PIC_REVIEW_STATUS_ENUM.PASS ? '管理员操作通过' : '管理员操作拒绝'
  // @ts-ignore
  const res = await doPictureReviewUsingPost({
    id: record.id,
    reviewStatus,
    reviewMessage,
  })
  if (res.data.code === 0) {
    message.success('审核操作成功')
    // 审核操作后重新获取数据
    fetchData()
  } else {
    message.error('审核操作失败，' + res.data.message)
  }
}

// 默认展示图片分类、图片标签
const categoryOptions = ref<String[]>([])
const tagOptions = ref<String[]>()

/**
 * 用于搜索框默认展示图片分类、图片标签
 */
const getTagCategoryOptions = async () => {
  const res = await listPictureTagCategoryUsingGet()
  if (res.data.code === 0 && res.data.data) {
    // @ts-ignore
    tagOptions.value = (res.data.data.tagList ?? []).map((data: String) => {
      return {
        value: data,
        label: data,
      }
    })
    // @ts-ignore
    categoryOptions.value = (res.data.data.categoryList ?? []).map((data: String) => {
      return {
        value: data,
        label: data,
      }
    })
  } else {
    message.error('默认分类标签列表展示失败，' + res.data.message)
  }
}

onMounted(() => {
  getTagCategoryOptions()
})

/**
 * 主色调搜索相似图片
 * @param color
 */
const onColorChange = async (color: string) => {
  loading.value = true
  const res = await searchPictureForAdminByColorUsingPost({
    picColor: color,
    // @ts-ignore
    spaceId: null,
  })
  if (res.data.code === 0 && res.data.data) {
    const data = res.data.data ?? []
    dataList.value = data
    total.value = data?.length
    message.success('匹配主色调相似图片成功，至多匹配18张图片')
  } else {
    message.error('匹配失败，' + res.data.message)
  }
  loading.value = false
}

/**
 * 重置搜索或匹配条件
 */
const clearSearchParams = () => {
  // 因为 SearchParams 是 reactive 对象
  // 所以不要直接置为空对象，最好是把每个字段值设置为 undefined 或空数组
  Object.keys(searchParams).forEach((key) => {
    searchParams[key as keyof typeof searchParams] = undefined
  })
  searchParams.tags = []
  // 初始化为空数组
  searchParams.tags = []
  searchParams.current = 1
  searchParams.pageSize = 18
  searchParams.sortField = ''
  searchParams.sortOrder = 'descend'
  // 清空后要通知父组件执行搜索
  fetchData()
  message.success('搜索条件或匹配方式已重置')
}
</script>

<style scoped></style>
